Error Handling
プログラムを落とさずに、決められた次の処理を行いたい
用語
table:用語
用語 意味
失敗 命名された処理が期待される処理を完了できなかった
エラーハンドリングの目的
例外が生じた際にプログラムがクラッシュすることは避けたい
続行不能にするのではなく、どうにかして継続させたい
できれば例外が起きる前の状態へrollbackしたい
せめてデータは整合性の取れる状態にしたい
生じた例外の原因の特定に寄与する
上に行くほど回復可能
デフォルト値
エラー値ではなく[]などのデフォルト値を返す
e.g. null, nil, Maybe, Optional
エラーであることのみを返す
直和
e.g. Either, Result, 多値リターン
エラーと正常系を両方返す
catch不能エラー
e.g. SwiftのfatalError()
そのエラーの責任が呼び出し元にある場合は、回復可能なエラーで返す
その処理の内部に問題がある場合は、回復不可能なエラーを返す
呼び出し元はその公開されているinterfaceからはどうしようもないので
関数というより、RESTFul APIとかformのようなものほうがイメージしやすい
何かエラーがあったときに、入力を変えて再度呼び出せば改善されるのかどうか
しかし、これ、回復可能性でエラーの方法を変えるの、どれぐらい妥当なのだろうかmrsekut.icon
例えば、回復不可能なエラーに対し、Eitther型を使うことにどういう問題があるのか
また、上記の分類も既存のerror値を分類しただけに過ぎない
例えば、effect typeのような他の新たな機構を前提すると、そもそも上記のような分類が不要になるということはないだろうか
swiftがそういうエラー分類をしているらしい
Simple domain errors (単純なドメインエラー)
Recoverable errors (回復可能なエラー)
Universal errors (普遍的なエラー)
Logic failures (論理的な失敗)
手続き的プログラミングでよく見るmrsekut.icon
例外を順々に関数の呼び出し元に例外を伝搬させていき、処理できる箇所で処理する
どこかで例外が起きた場合は処理が中断され、
その関数の呼び出し元、それの呼び出し元、、と巻き戻っていく
try節の中まで戻ってきたら、catch節の処理へ移行する
catchの中で回復しきれないときは、さらに例外を投げることもある
code:ts
try { .. } catch (e: Error) { throw e; }
関数を見た時に、それが例外を発しうるかどうかを見た目で判断できない
関数型プログラミングでよく見るmrsekut.icon
Errorを表す型を用いて、Errorを値として扱う
具体的にはMaybeやEitherなど
関数の型に現れるので、型を見ればそれが失敗しうるのかどうか判別できる
値用いたError Handling
Go言語とか
関数が(value, error)の2値を返し、呼び出し側がhandlingする
React ComponentレベルのError Handling
子Componentがthrowしたものを、親Componentがhandlingして、「エラーが発生しました」のようなUIを表示する
errorを表すglobal変数を使う
Shell Sciprtのエラーって2だったらなんたらみたいなのよな、と思い出した
C言語もShellScriptも詳しくないので、これが似たものなのかそうではないのかの判断ができないmrsekut.icon
C言語には例外処理がない(?)
JavaScript
現状stage2の機能について
Julia
Elixir
ゴール指向評価の機能によって、例外処理用の文法を言語に導入しなくても、つまり、例外処理のための記述を意識せずにふつうにプログラムを書いてるだけで例外処理が入っているということになる
デメリットは例外処理が目立たなくなってしまうこと
つまり、普通の言語と見た目が変わってしまうMatz.icon
普通にこれ良いのでは?mrsekut.icon
エラー処理のせいで、本筋の処理が埋もれる問題の対処
よくまとまっている
Nim
エラーが起きたときに、どのようなメッセージを出力するか
参考
2014年の例外アドベントカレンダーの目次的なもの
実際は頓挫されたようで詳細の記事は4つしかないが、目次として勉強の道標になる
超堅牢なやつ